package com.bgi.cg.oss4j.provider.huawei.service;

import com.bgi.cg.api.AbstractOssService;
import com.bgi.cg.api.entity.OssResponse;
import com.bgi.cg.oss4j.common.factory.BeanFactory;
import com.bgi.cg.oss4j.common.util.OssUtil;
import com.bgi.cg.oss4j.provider._base.OssSupplierType;
import com.bgi.cg.oss4j.provider.huawei.config.HuaweiOssConfig;
import com.obs.services.ObsClient;
import com.obs.services.model.*;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.concurrent.Executor;
import java.util.function.Function;

/**
 * @Description 华为云
 * @Author Z.cg
 * @Date 2023/9/8
 * @Version 1.0
 **/
@Slf4j
public class HuaweiOssService extends AbstractOssService {
    private final HuaweiOssConfig config;
    private ObsClient client;

    public HuaweiOssService(HuaweiOssConfig huaweiOssConfig, Executor pool) {
        super(pool);
        this.config = huaweiOssConfig;
        client = new ObsClient(huaweiOssConfig.getAccessKey(), huaweiOssConfig.getAccessKeySecret(), huaweiOssConfig.getEndPoint());
        if (huaweiOssConfig.isBucketAutoCreate()) {
            try {
                if (!hasBucket(huaweiOssConfig.getBucket())) {
                    client.createBucket(huaweiOssConfig.getBucket(), huaweiOssConfig.getRegion());
                }
            } catch (Exception exception) {
                log.error("【{}】OBS创建bucket失败：{}", OssSupplierType.HUAWEI.name(), exception.getMessage());
            }

        }
    }

    @Override
    public OssResponse upload(File file) {
        return upload(file, config.getBucket());
    }

    @Override
    public OssResponse upload(File file, String bucketName) {
        return upload(file, bucketName, OssUtil::generatePath);
    }

    @Override
    public OssResponse upload(File file, Function<File, String> fileKeyFunction) {
        return upload(file, config.getBucket(), fileKeyFunction);
    }

    @Override
    public OssResponse upload(File file, String bucketName, Function<File, String> fileKeyFunction) {
        valiConfigIsOk();
        // 生成存储的文件名即存储的路径
        String fileName = fileKeyFunction.apply(file);
        OssResponse ossResponse = OssResponse.builder().code("0").ossType(OssSupplierType.HUAWEI.name()).build();
        PutObjectResult result = client.putObject(bucketName, fileName, file);
        if (result.getStatusCode() == 200) {
            ossResponse.setFilePath(result.getObjectKey());
            ossResponse.setPreviewUrl(result.getObjectUrl());
            // CDN访问域名URL配置，则使用 url+objectKey的方式ifangwen
        } else {
            log.error("【{}】OBS文件上传失败：{}", OssSupplierType.HUAWEI.name(), result.getStatusCode());
            ossResponse.setFail("上文文件失败，状态码：{}", String.valueOf(result.getStatusCode()));
            ossResponse.setCode(String.valueOf(result.getStatusCode()));
        }
        return ossResponse;
    }

    @Override
    public OssResponse genPreviewUrl(String fileName) {
        return genPreviewUrl(fileName, config.getBucket());
    }

    @Override
    public OssResponse genPreviewUrl(String fileName, String bucketName) {
        TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, BeanFactory.getOssConfig().getDownloadUrlExpireMs());
        request.setBucketName(bucketName);
        request.setObjectKey(fileName);
        TemporarySignatureResponse response = client.createTemporarySignature(request);
        OssResponse ossResponse = OssResponse.builder().code("0").previewUrl(response.getSignedUrl()).build();
        return ossResponse;
    }

    @Override
    public OssResponse delete(String fileName) {
        return delete(fileName, config.getBucket());
    }

    @Override
    public OssResponse delete(String fileName, String bucketName) {
        DeleteObjectResult deleteObjectResult = client.deleteObject(bucketName, fileName);
        if (deleteObjectResult.isDeleteMarker()) {
            return OssResponse.builder().code("0").build();
        }
        // 删除失败了
        return OssResponse.builder().code("-1").build();
    }

    boolean hasBucket(String buctetName) {
        try {
            AccessControlList accessControlList = client.getBucketAcl(buctetName);
            return accessControlList != null && accessControlList.getGrantAndPermissions().length > 0 && accessControlList.getStatusCode() == 200;
        } catch (Exception exception) {
            log.error("【{}】OBS接口访问失败：{}", OssSupplierType.HUAWEI.name(), exception.getMessage());
            return false;
        }
    }

    void valiConfigIsOk() {
        if (!config.configIsOk()) {
            throw new RuntimeException("未配置[accessKey,accessKeySecret,bucket,endPoint,region]值");
        }
    }
}
